/**
 * Copyright (c) 2015-2030 by Beijing Yanlight Co., Ltd.
 * All rights reserved.
 */
package com.yanlight.support.wx.util;

import java.io.IOException;
import java.util.SortedMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yanlight.util.LogUtil;
import org.apache.commons.lang3.StringUtils;

import com.yanlight.support.wx.WxConstants;
import com.yanlight.support.wx.model.WxJsPaySign;
import com.yanlight.support.wx.model.WxOrder;
import com.yanlight.support.wx.model.WxSnsOauth;
import com.yanlight.support.wx.request.WxExchangeRequest;
import com.yanlight.support.wx.request.WxOrderRequest;
import com.yanlight.support.wx.response.WxExchangeResponse;
import com.yanlight.support.wx.response.WxOrderResponse;
import com.yanlight.util.EncryptUtil;
import com.yanlight.util.RandomStringUtil;

/**
 * @author haolw
 * @time 2017/07/20
 */
public abstract class WxUtil {

    /**
     * 获取用户openid，用户授权回调，snsapi_base模式 ，当前url通过base64安全模式编码。
     * callbackUrl需要接收code和url这两个参数
     *
     * @param request
     * @param response
     * @param appid
     * @param callbackUrl
     */
    public static void userAuthorizeBase(HttpServletRequest request, HttpServletResponse response, String appid,
                                         String callbackUrl) {
        userAuthorize(request, response, appid, callbackUrl, WxConstants.WX_BASE_SCOPE);
    }

    /**
     * 获取用户openid，用户授权回调，snsapi_userinfo模式 ，当前url通过base64安全模式编码。
     * callbackUrl需要接收code和url这两个参数
     *
     * @param request
     * @param response
     * @param appid
     * @param callbackUrl
     */
    public static void userAuthorizeUserinfo(HttpServletRequest request, HttpServletResponse response, String appid,
                                             String callbackUrl) {
        userAuthorize(request, response, appid, callbackUrl, WxConstants.WX_USERINFO_SCOPE);
    }

    /**
     * 获取用户openid，用户授权回调
     *
     * @param request
     * @param response
     * @param appid
     * @param callbackUrl
     * @param type
     */
    private static void userAuthorize(HttpServletRequest request, HttpServletResponse response, String appid,
                                      String callbackUrl, String type) {
        String queryString = request.getQueryString();
        String path = request.getServletPath();
        String redirectUrl = path;
        if (StringUtils.isNotBlank(queryString)) {
            redirectUrl = path.concat("?").concat(queryString);
        }
        redirectUrl = EncryptUtil.encodeBase64Safe(redirectUrl);
        StringBuilder url = new StringBuilder(WxConstants.WX_AUTHORIZE_URL);
        url.append("?appid=" + appid);
        url.append("&redirect_uri=");
        url.append(callbackUrl + "?url=");
        url.append(redirectUrl);
        url.append("&response_type=code");
        url.append("&scope=" + type);
        url.append("&state=STATE");
        url.append("#wechat_redirect");

        try {
            response.sendRedirect(url.toString());
        } catch (IOException e) {
            throw new IllegalArgumentException(e);
        }
        return;
    }

    /**
     * 通过回调的code换取用户的openid
     *
     * @param appId
     * @param appSecret
     * @param code
     * @return
     */
    public static WxSnsOauth getOpenId(String appId, String appSecret, String code) {
        WxExchangeRequest exchangeRequest = new WxExchangeRequest();
        exchangeRequest.setAppId(appId);
        exchangeRequest.setCode(code);
        exchangeRequest.setSecret(appSecret);
        WxExchangeResponse response = exchangeRequest.execute();
        WxSnsOauth snsOauth = null;
        if (StringUtils.isEmpty(response.getErrmsg())) {
            snsOauth = new WxSnsOauth();
            snsOauth.setAccessToken(response.getAccess_token());
            snsOauth.setExpiresIn(response.getExpires_in());
            snsOauth.setOpenid(response.getOpenid());
        } else {
            throw new IllegalArgumentException(response.errorInfo());
        }
        return snsOauth;
    }

    /**
     * js支付签名
     *
     * @param appId
     * @param mchKey
     * @param prepayId
     * @return
     */
    public static WxJsPaySign jsPaySign(String appId, String mchKey, String prepayId) {
        WxJsPaySign paySign = new WxJsPaySign();
        String nonceStr = RandomStringUtil.randomAlphanumeric(32);
        String timestamp = String.valueOf(System.currentTimeMillis());
        paySign.setAppId(appId);
        paySign.setPackageStr(prepayId);
        paySign.setNonceStr(nonceStr);
        paySign.setTimeStamp(timestamp);
        String sign = SignatureUtil.createApiSign(paySign.signParams(), mchKey);
        paySign.setPaySign(sign);
        return paySign;
    }

    /**
     * 统一下单
     *
     * @param mchKey
     * @param request
     */
    public static WxOrder placeOrder(String mchKey, WxOrderRequest request) {
        SortedMap<String, String> paramsMap = request.getParamsMap();
        String nonceStr = RandomStringUtil.randomAlphanumeric(32);
        paramsMap.put("nonce_str", nonceStr);
        String sign = SignatureUtil.createApiSign(paramsMap, mchKey);
        String body = paramsMap.get("body");
        paramsMap.put("body", "<![CDATA[" + body + "]]>");
        paramsMap.put("sign", "<![CDATA[" + sign + "]]>");
        WxOrderResponse response = request.execute();
        return response.toSpec();
    }

}
